package ru.compscicenter.uno.view;

import ru.compscicenter.uno.model.Card;
import ru.compscicenter.uno.util.ImagePool;

import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.Border;

public class CardImage extends JComponent {

    private BufferedImage image;
    private Card card;
    private String path;
    private static final double PROPORTION = 1.532;
    private static final int DEFAULT_WIDTH = 83;
    private static final int DEFAULT_HEIGHT = 127;
    private static final String DIR = "res/img/cards/";
    private boolean isHighRender = true;

    public CardImage(Card card, Card.Color selectedColorForWildCard) {
        this.card = card;
        this.card = card;
        String resourcePath = getResourcePathForWildCard(card, selectedColorForWildCard);
        init(resourcePath);
    }

    public CardImage(Card card) {
        this.card = card;
        String resourcePath = getResourcePath(card);
        init(resourcePath);
    }

    private void init(String path) {
        this.path = path;

        setBounds(getX(), getY(), DEFAULT_WIDTH, DEFAULT_HEIGHT);
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                if (isHighRender) {
                    //load rescaled image from pool
                    loadImage();
                } else {
                    //or load image only first time
                    if(image == null){
                        loadImage();
                    }
                }
                repaint();
            }
        });
        Border border = BorderFactory.createLineBorder(Color.BLACK);
        setBorder(border);
    }

    private void loadImage() {
        image = ImagePool.getImage(path, getWidth(), getHeight());
    }

    public static int getProportionWidth(int height) {
        return (int) Math.round(height / PROPORTION);
    }

    public static int getProportionHeight(int width) {
        return (int) Math.round(width * PROPORTION);
    }

    public boolean isHighRender() {
        return isHighRender;
    }

    public void setHighRender(boolean highRender) {
        isHighRender = highRender;
    }

    @Override
    public void paintComponent(Graphics g) {
        if (isHighRender) {
            //scaling by lib
            g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
        } else {
            //scaling by graphics
            int w = getWidth();
            int h = getHeight();
            if (w > h) {
                w = getProportionWidth(h);
            } else {
                h = getProportionHeight(w);
            }

            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(image, 0, 0, w, h, null);
        }
    }

    public Card getCard() {
        return card;
    }

    private static String getResourcePathForWildCard(Card card, Card.Color topColor) {
        if (card == null) {
            return DIR + "back.png";
        }
        String cardType = null;
        switch (card.getType()) {
            case WILD:
                cardType = "color";
                break;
            case WILD_TAKE_FOUR:
                cardType = "plus4";
                break;
            default:
                throw new IllegalStateException("invalid card type in cardImage path selector");
        }
        String cardColor = "";
        switch (topColor) {
            case YELLOW:
                cardColor = "_yellow";
                break;
            case RED:
                cardColor = "_red";
                break;
            case GREEN:
                cardColor = "_green";
                break;
            case BLUE:
                cardColor = "_blue";
                break;
            case ANY:
                cardColor = "";
        }
        return DIR + cardType + cardColor + ".png";
    }

    private static String getResourcePath(Card card) {
        if (card == null) {
            return DIR + "back.png";
        }

        String cardColor = "";
        if (card.isColored()) {
            switch (card.getColor()) {
                case YELLOW:
                    cardColor = "yellow_";
                    break;
                case RED:
                    cardColor = "red_";
                    break;
                case GREEN:
                    cardColor = "green_";
                    break;
                case BLUE:
                    cardColor = "blue_";
                    break;
                case ANY:
                    throw new IllegalArgumentException("Invalid color to draw");
            }
        }
        String cardType = null;
        switch (card.getType()) {
            case NUM_0:
                cardType = "0";
                break;
            case NUM_1:
                cardType = "1";
                break;
            case NUM_2:
                cardType = "2";
                break;
            case NUM_3:
                cardType = "3";
                break;
            case NUM_4:
                cardType = "4";
                break;
            case NUM_5:
                cardType = "5";
                break;
            case NUM_6:
                cardType = "6";
                break;
            case NUM_7:
                cardType = "7";
                break;
            case NUM_8:
                cardType = "8";
                break;
            case NUM_9:
                cardType = "9";
                break;
            case REVERSE:
                cardType = "reverse";
                break;
            case TAKE_TWO:
                cardType = "plus2";
                break;
            case SKIP:
                cardType = "skip";
                break;
            case WILD:
                cardType = "color";
                break;
            case WILD_TAKE_FOUR:
                cardType = "plus4";
                break;
        }
        return DIR + cardColor + cardType + ".png";
    }
}
